<template>
  <div class="grid" style="gap: 12px">
    <GlassCard>
      <el-form label-position="top" label-width="auto">
        <div
          class="row"
          style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px">
          <el-form-item label="本金">
            <el-input-number
              v-model="state.principal"
              :min="0"
              :step="100"
              controls-position="right" />
          </el-form-item>
          <el-form-item label="利率（%）">
            <el-input-number
              v-model="state.ratePercent"
              :min="0"
              :max="100"
              :step="0.1"
              controls-position="right" />
          </el-form-item>
        </div>

        <div
          class="row"
          style="display: grid; grid-template-columns: 1fr; gap: 12px">
          <el-form-item label="计息期数">
            <el-input-number
              v-model="state.periods"
              :min="0"
              :step="1"
              controls-position="right" />
          </el-form-item>
        </div>

        <!-- 可选：每期追加与追加时点
      <div class="row" style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px">
        <el-form-item label="每期追加">
          <el-input-number v-model="state.contribution" :min="0" :step="10" />
        </el-form-item>
      </div>
      <el-form-item label="追加时点">
        <el-radio-group v-model="state.timing">
          <el-radio-button label="end">期末</el-radio-button>
          <el-radio-button label="start">期初</el-radio-button>
        </el-radio-group>
      </el-form-item>
      -->

        <!-- <el-form-item label="追加时点">
        <el-radio-group v-model="state.timing">
          <el-radio-button label="end">期末</el-radio-button>
          <el-radio-button label="start">期初</el-radio-button>
        </el-radio-group>
      </el-form-item> -->

        <div class="result-box">
          <div class="line font-bold">
            结果：<span class="value">{{ futureValueText }}</span>
          </div>
          <div class="line profit font-bold">
            利润：<span class="value">{{ profitText }}</span>
          </div>
        </div>

        <div class="formula-box">
          <div>计算公式：</div>
          <div>A = P × (1 + r)^n</div>
          <div>利润 = A − P</div>
          <div>说明：P 为本金，r 为每期利率（百分比/100），n 为计息期数。</div>
        </div>
      </el-form>
    </GlassCard>
  </div>
</template>

<script setup lang="ts">
import {
  ElForm,
  ElFormItem,
  ElInputNumber,
  ElOption,
  ElRadioButton,
  ElRadioGroup,
  ElSelect
} from "element-plus"
import { computed, reactive } from "vue"

// @ts-ignore - SFC default export by Vue plugin
import GlassCard from "./ui/GlassCard.vue"

type CompoundParams = {
  principal: number
  rate: number
  periods: number
  contribution: number
  contributionAtStart: boolean
}

function computeCompound({
  principal,
  rate,
  periods,
  contribution,
  contributionAtStart
}: CompoundParams): number {
  // Here `rate` is the per-period nominal rate.
  const r = rate
  const n = periods
  // Handle zero or near-zero rate to avoid division by zero and NaN
  if (Math.abs(r) < 1e-12) {
    return safeAdd(principal, safeMul(contribution, n))
  }
  const growth = pow1pr(r, n)
  let future = safeMul(principal, growth)
  if (contribution !== 0) {
    const factor = safeDiv(safeSub(growth, 1), r)
    const adj = contributionAtStart ? safeAdd(1, r) : 1
    future = safeAdd(future, safeMul(safeMul(contribution, adj), factor))
  }
  return roundTo(future)
}

const state = reactive({
  principal: 10000,
  ratePercent: 5,
  periods: 10,
  contribution: 0,
  timing: "end" as "start" | "end"
})

function getPerPeriodRate(): number {
  // 输入的利率单位与选择的频率一致：
  //  - 按年：输入为年利率 -> 每期利率 = 年利率
  //  - 按季度：输入为季利率 -> 每期利率 = 季利率
  //  - 按月：输入为月利率 -> 每期利率 = 月利率
  //  - 按日：输入为日利率 -> 每期利率 = 日利率
  return state.ratePercent / 100
}

const futureValue = computed(() =>
  computeCompound({
    principal: state.principal,
    rate: getPerPeriodRate(),
    periods: state.periods,
    contribution: state.contribution,
    contributionAtStart: state.timing === "start"
  })
)

const futureValueText = computed(() => futureValue.value.toFixed(2))

// Profit = final amount - principal - total contributions
const totalContributions = computed(() => state.contribution * state.periods)
const profit = computed(() =>
  roundTo(
    safeSub(
      safeSub(futureValue.value, state.principal),
      totalContributions.value
    )
  )
)
const profitText = computed(() => profit.value.toFixed(2))

// ---------- Precision helpers ----------
const DECIMAL_PLACES = 12
function roundTo(value: number, places = DECIMAL_PLACES): number {
  const factor = 10 ** places
  return Math.round((value + Number.EPSILON) * factor) / factor
}
function safeAdd(a: number, b: number): number {
  return roundTo(a + b)
}
function safeSub(a: number, b: number): number {
  return roundTo(a - b)
}
function safeMul(a: number | bigint, b: number | bigint): number {
  return roundTo(Number(a) * Number(b))
}
function safeDiv(a: number, b: number): number {
  return roundTo(a / b)
}
// Compute (1 + r)^n with rounding each step to mitigate FP drift
function pow1pr(rate: number, n: number): number {
  let base = roundTo(1 + rate)
  let res = 1
  let e = Math.floor(n)
  while (e > 0) {
    if (e & 1) res = safeMul(res, base)
    base = safeMul(base, base)
    e >>= 1
  }
  return res
}
</script>

<style scoped lang="less">
.result-box {
  background: #ffffff;
  border: 1px solid #e3edf5;
  border-radius: 10px;
  padding: 12px;
  text-align: left;
}
.result-box .line {
  margin: 2px 0;
  font-size: 18px;
}
.result-box .line.profit {
  color: #e04141;
}
.result-box .value {
  font-family:
    "Manrope",
    "Inter",
    "Roboto",
    "SF Pro Display",
    system-ui,
    -apple-system,
    "Helvetica Neue",
    Arial,
    "Noto Sans",
    sans-serif;
  font-weight: 800;
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings:
    "tnum" 1,
    "lnum" 1;
  letter-spacing: 0.3px;
  margin-left: 6px;
}

.formula-box {
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid #e3edf5;
  border-radius: 10px;
  padding: 10px;
  text-align: left;
  line-height: 1.6;
  margin-top: 8px;
  font-size: 12px;
}
</style>
